#include <soar.h>

#define CHILD_NUM               4

static void sig_child(int signo)
{/*{{{*/
    pid_t pid;
    int stat;

    while((pid=waitpid(-1, &stat, WNOHANG)) > 0)
        fprintf(stderr, "child(%d): terminated\n", pid);
}/*}}}*/

static int func_child(SOCKET listen_sock)
{/*{{{*/
    unsigned char *msg_in=NULL, *msg_out=NULL;
    int msg_in_size, msg_out_size;
    pid_t pid=getpid();

    ALLOC_MULTI(msg_in, unsigned char, SOCK_MSG_SIZE, GO_OUT);
    //ALLOC_MULTI(msg_out, unsigned char, SOCK_MSG_SIZE, GO_OUT);
    //
    while(1)
    {
        SOCKET new_sock;
        new_sock=sock_accept(listen_sock, -1);
        if(new_sock == INVALID_SOCKET)
        {
            fprintf(stderr, "child(%ld): socket accept fail\n",
                    (long)pid);
            continue;
        }
        struct sock_info sock_info;
        sock_get_info(new_sock, &sock_info);
        fprintf(stderr, "child(%ld): self: %s %d | peer: %s %d\n",
                (long)pid,
                sock_info.self_ip, sock_info.self_port,
                sock_info.peer_ip, sock_info.peer_port);

        while(1)
        {
            if(sock_read(new_sock, msg_in, &msg_in_size, -1, WRAP))
            {
                fprintf(stderr, "child(%ld): sock_read fail\n",
                        (long)pid);
                break;
            }
            //memcpy(msg_out, msg_in, msg_in_size);
            msg_out=msg_in;
            msg_out_size=msg_in_size;
            if(sock_write(new_sock, msg_out, &msg_out_size, -1, WRAP))
            {
                fprintf(stderr, "child(%ld): sock_write fail\n",
                        (long)pid);
                break;
            }
        }
        sock_close(new_sock);
    }

GO_OUT:
    FREE(msg_in);
    //FREE(msg_out);
    sock_close(listen_sock);
    return(0);
}/*}}}*/

int main(int argc, char *argv[])
{/*{{{*/
    int rtn;

    printf("pid: %d\n", getpid());

    sig_set_handler(SIGCHLD, sig_child);

    int server_port=20000;
    SOCKET listen_sock=sock_listen(server_port);
    if(listen_sock == INVALID_SOCKET)
    {
        fprintf(stderr, "socket listen fail\n");
        return(-1);
    }

    int i;
    for(i=0; i<CHILD_NUM; ++i)
    {
        pid_t pid=fork();
        if(pid == 0)
        {
            if(func_child(listen_sock))
            {
                fprintf(stderr, "child(%ld): abort\n", (long)getpid());
            }
            return(0);
        }
        if(pid == -1)
        {
            fprintf(stderr, "fork child(%d): fail\n", i);
            rtn=-1; goto GO_OUT;
        }
        printf("fork child(%d:%d)\n", i, pid);
    }

    DEEP_SLEEP;
    rtn=0;

GO_OUT:
    sock_close(listen_sock);
    return(rtn);
}/*}}}*/
